package com.eddie.xhttpurlconnection;

import android.annotation.SuppressLint;
import android.os.Handler;
import android.os.Message;

import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;


//问题：
//1.httpURLConnection怎么添加拦截器？
//2.文件以流的形式从服务器读取，1024个字节，读到本地，再去服务器读1024个字节吗？

/**
 * @author yanpf
 * @create 2019/1/25 0025
 * @Describe 请求工具
 */
public class XHttpUtils {


    private static XHttpUtils mInstance;
    private OnRequestListener mOnRequestListener;
    private OnDownloadListener mOnDownloadListener;

    private final int REQUEST_SUCCESS = 0;
    private final int REQUEST_FAIL = 1;

    private final int DOWNLOAD_PROGESS = 2;
    private final int DOWNLOAD_FAIL = 3;
    private final int DOWNLOAD_COMPLETE = 4;

    private HttpURLConnection mHttpURLConnection = null;

    private int mConnectTimeout;
    private int mReadTimeout;

    @SuppressLint("HandlerLeak")
    private Handler mHandler = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.arg1) {
                case REQUEST_SUCCESS:
                    mOnRequestListener.onSuccess(msg.obj.toString());
                    break;
                case REQUEST_FAIL:
                    mOnRequestListener.onFail(msg.arg2);
                    break;
                case DOWNLOAD_PROGESS:
                    mOnDownloadListener.curentProgress(msg.arg2);
                    break;
                case DOWNLOAD_FAIL:
                    mOnDownloadListener.onFail(msg.arg2);
                    break;
                case DOWNLOAD_COMPLETE:
                    mOnDownloadListener.complete();
                    break;
            }
        }

    };

    /**
     * 构造方法
     */
    public XHttpUtils() {
    }

    /**
     * 构造函数
     *
     * @param builder
     */
    public XHttpUtils(Builder builder) {
        this.mConnectTimeout = builder.connectTimeout;
        this.mReadTimeout = builder.readTimeout;
    }

    /**
     * 初始化对象
     */
    public void init() {
        if (mInstance == null) {
            mInstance = new XHttpUtils();
        }
    }

    /**
     * Builder类
     */
    public static class Builder {

        private int connectTimeout;
        private int readTimeout;

        public Builder() {
        }

        public Builder connectTimeout(int connectTimeout) {
            this.connectTimeout = connectTimeout;
            return this;
        }


        public Builder readTimeout(int readTimeout) {
            this.readTimeout = readTimeout;
            return this;
        }

        public XHttpUtils build() {
            return new XHttpUtils(this);
        }

    }

    /**
     * xHttpGet
     *
     * @param address
     * @param onRequestListener
     */
    public static void xGet(String address, OnRequestListener onRequestListener) {
        mInstance.get(address, onRequestListener);
    }

    /**
     * get请求
     *
     * @param address
     * @param onRequestListener
     */
    public void get(final String address, OnRequestListener onRequestListener) {

        mOnRequestListener = onRequestListener;
        mOnRequestListener.onBefore();

        new Thread(new Runnable() {

            @Override
            public void run() {

                BufferedReader reader = null;
                try {
                    URL url = new URL(address);
                    mHttpURLConnection = (HttpURLConnection) url.openConnection();
                    //设置连接主机超时时间
                    mHttpURLConnection.setConnectTimeout(mConnectTimeout);
                    //设置从主机读取超时时间
                    mHttpURLConnection.setReadTimeout(mReadTimeout);
                    //设置请求中的媒体类型信息。
                    mHttpURLConnection.setRequestProperty("Content-Type", "application/json");
                    //设置客户端与服务连接类型
                    mHttpURLConnection.addRequestProperty("Connection", "Keep-Alive");
                    mHttpURLConnection.setRequestMethod("GET");
                    // 开始连接
                    mHttpURLConnection.connect();
                    // 判断请求是否成功
                    if (mHttpURLConnection.getResponseCode() == 200) {
                        // 获取返回的数据
                        InputStream inputStream = mHttpURLConnection.getInputStream();
                        reader = new BufferedReader(new InputStreamReader(inputStream));
                        final StringBuilder response = new StringBuilder();
                        String line;
                        while ((line = reader.readLine()) != null) {
                            response.append(line);
                        }
                        Message message = new Message();
                        message.arg1 = REQUEST_SUCCESS;
                        message.obj = response.toString();
                        mHandler.sendMessage(message);
                    } else {
                        Message message = new Message();
                        message.arg1 = REQUEST_FAIL;
                        message.arg2 = mHttpURLConnection.getResponseCode();
                        mHandler.sendMessage(message);
                    }
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                    Message message = new Message();
                    message.arg1 = REQUEST_FAIL;
                    message.arg2 = 404;
                    mHandler.sendMessage(message);
                } catch (IOException e) {
                    e.printStackTrace();
                    Message message = new Message();
                    message.arg1 = REQUEST_FAIL;
                    message.arg2 = 404;
                    mHandler.sendMessage(message);
                } finally {
                    if (reader != null) {
                        try {
                            reader.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        if (mHttpURLConnection != null) {
                            mHttpURLConnection.disconnect();
                        }
                    }
                }
            }
        }).start();
    }

    /**
     * xHttpGet
     *
     * @param address
     * @param onRequestListener
     */
    public static void xPost(String address, Map<String, String> params, OnRequestListener onRequestListener) {
        mInstance.post(address, params, onRequestListener);
    }

    /**
     * post请求
     *
     * @param address
     * @param params
     * @param onRequestListener
     */
    public void post(final String address, Map<String, String> params, OnRequestListener onRequestListener) {

        final StringBuffer out = new StringBuffer();
        // 组织请求参数
        for (String key : params.keySet()) {
            if (out.length() != 0) {
                out.append("&");
            }
            out.append(key).append("=").append(params.get(key));
        }

        mOnRequestListener = onRequestListener;
        mOnRequestListener.onBefore();

        new Thread(new Runnable() {

            @Override
            public void run() {

                BufferedReader reader = null;
                try {
                    URL url = new URL(address);
                    mHttpURLConnection = (HttpURLConnection) url.openConnection();
                    //设置连接主机超时时间
                    mHttpURLConnection.setConnectTimeout(mConnectTimeout);
                    //设置从主机读取超时时间
                    mHttpURLConnection.setReadTimeout(mReadTimeout);
                    mHttpURLConnection.setRequestProperty("accept", "*/*");
                    //设置客户端与服务连接类型
                    mHttpURLConnection.addRequestProperty("Connection", "Keep-Alive");
                    mHttpURLConnection.setRequestProperty("Content-Length", String.valueOf(out.length()));
                    mHttpURLConnection.setRequestMethod("POST");

                    // 设置运行输入
                    mHttpURLConnection.setDoInput(true);
                    // 设置运行输出
                    mHttpURLConnection.setDoOutput(true);

                    PrintWriter printWriter = new PrintWriter(mHttpURLConnection.getOutputStream());
                    // 发送请求参数
                    printWriter.write(out.toString());
                    // flush输出流的缓冲
                    printWriter.flush();
                    printWriter.close();

                    // 判断请求是否成功
                    if (mHttpURLConnection.getResponseCode() == 200) {
                        // 获取返回的数据
                        InputStream inputStream = mHttpURLConnection.getInputStream();
                        reader = new BufferedReader(new InputStreamReader(inputStream));
                        final StringBuilder response = new StringBuilder();
                        String line;
                        while ((line = reader.readLine()) != null) {
                            response.append(line);
                        }
                        Message message = new Message();
                        message.arg1 = REQUEST_SUCCESS;
                        message.obj = response.toString();
                        mHandler.sendMessage(message);
                    } else {
                        Message message = new Message();
                        message.arg1 = REQUEST_FAIL;
                        message.arg2 = mHttpURLConnection.getResponseCode();
                        mHandler.sendMessage(message);
                    }
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                    Message message = new Message();
                    message.arg1 = REQUEST_FAIL;
                    message.arg2 = 404;
                    mHandler.sendMessage(message);
                } catch (IOException e) {
                    e.printStackTrace();
                    Message message = new Message();
                    message.arg1 = REQUEST_FAIL;
                    message.arg2 = 404;
                    mHandler.sendMessage(message);
                } finally {
                    if (reader != null) {
                        try {
                            reader.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        if (mHttpURLConnection != null) {
                            mHttpURLConnection.disconnect();
                        }
                    }
                }
            }
        }).start();
    }

    /**
     * 下载文件
     */
    public static void xDownloadFile(String downloadUrl, String filePath, OnDownloadListener onDownloadListener) {
        mInstance.downloadFile(downloadUrl, filePath, onDownloadListener);
    }

    /**
     * 下载文件
     */
    public void downloadFile(final String downloadUrl, final String filePath, OnDownloadListener onDownloadListener) {

        mOnDownloadListener = onDownloadListener;
        mOnDownloadListener.before();

        new Thread(new Runnable() {
            @Override
            public void run() {

                try {
                    //构建URL地址
                    URL url = new URL(downloadUrl);
                    //打开打开
                    mHttpURLConnection = (HttpURLConnection) url.openConnection();
                    //设置连接主机超时时间
                    mHttpURLConnection.setConnectTimeout(mConnectTimeout);
                    //设置从主机读取超时时间
                    mHttpURLConnection.setReadTimeout(mReadTimeout);
                    mHttpURLConnection.setRequestMethod("GET");
                    //可设置请求头
                    mHttpURLConnection.setRequestProperty("Content-Type", "application/octet-stream");
                    // 维持长连接
                    mHttpURLConnection.setRequestProperty("Connection", "Keep-Alive");
                    mHttpURLConnection.setRequestProperty("Charset", "UTF-8");

                    // 判断请求是否成功
                    if (mHttpURLConnection.getResponseCode() == 200) {
                        //获取数据流内容
                        InputStream is = mHttpURLConnection.getInputStream();
                        //获取文件长度
                        int fileLength = mHttpURLConnection.getContentLength();
                        //写入文件
                        OutputStream os = new FileOutputStream(filePath);
                        int length;
                        int lengtsh = 0;
                        byte[] bytes = new byte[1024];
                        while ((length = is.read(bytes)) != -1) {
                            os.write(bytes, 0, length);
                            //获取当前进度值
                            lengtsh += length;
                            Message message = new Message();
                            message.arg1 = DOWNLOAD_PROGESS;
                            //i 增加数量，mBNumber 总数
                            float pressent = (float) lengtsh / fileLength * 100;
                            message.arg2 = (int) pressent;
                            mHandler.sendMessage(message);
                        }
                        is.close();
                        os.close();
                        os.flush();
                        Message message = new Message();
                        message.arg1 = DOWNLOAD_COMPLETE;
                        mHandler.sendMessage(message);
                    } else {
                        Message message = new Message();
                        message.arg1 = DOWNLOAD_FAIL;
                        message.arg2 = mHttpURLConnection.getResponseCode();
                        mHandler.sendMessage(message);
                    }
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                    Message message = new Message();
                    message.arg1 = DOWNLOAD_FAIL;
                    message.arg2 = 404;
                    mHandler.sendMessage(message);
                } catch (IOException e) {
                    e.printStackTrace();
                    Message message = new Message();
                    message.arg1 = DOWNLOAD_FAIL;
                    message.arg2 = 404;
                    mHandler.sendMessage(message);
                }

            }
        }).start();

    }

}
